home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
v10n15.arc
/
STRINGS.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-08-09
|
82KB
|
2,202 lines
page 66,132
;============================================================================
; STRINGS.COM - a set of string handling functions for batch files.
;
; Syntax:
; STRINGS [/H][/M][/Pc ][var = ] function arg1 [, arg2] [, arg3]
;
; /? - Print help message
; /M - Use master environment block
; /Pc - Use c as parse character instead of ','
;
; Revision History:
;
; Version 1.0 Initial Release
;
;============================================================================
code segment
assume cs:code
org 2ch
local_environment dw ? ;Word containing the segment
; of the program's env. block.
org 80h
command_tail db ? ;Offset of the command tail.
org 100h
main: jmp initialize
program db 13,10,"STRINGS 1.0 "
copyright db "(c) 1991 Douglas Boling",10,13
db "First published in PC Magazine, September 10, 1991"
db 10,13,10,"$",1Ah
VAR_SIZE equ 128 ;Max size of variables
DATABUFF_SIZE equ 16384 ;Size of file data buffer
command_table db "LEFT",0 ;String functions
db "RIGHT",0
db "MID",0
db "LENGTH",0
db "FIND",0
db "FINDC",0
db "LOWER",0
db "UPPER",0
db "CHAR",0
db "VAL",0
db "FILENAME",0
db "FILEEXT",0
db "READ",0 ;File functions
db "WRITE",0
db "FILESIZE",0
db "LINESIZE",0
db "TRUENAME",0
db "VER",0 ;System functions
db "ASK",0
db "ENVFREE",0
db "ENVSIZE",0
db "MASTERVAR",0
db "ADD",0 ;Math functions
db "SUB",0
db "MUL",0
db "DIV",0
db 0 ;End of list flag
jump_table dw offset left_str
dw offset right_str
dw offset mid_str
dw offset length_str
dw offset find_str
dw offset findc_str
dw offset lower_str
dw offset upper_str
dw offset char_str
dw offset val_str
dw offset filename_str
dw offset fileext_str
dw offset readrec_file
dw offset writerec_file
dw offset filesize_file
dw offset numrec_file
dw offset truename_file
dw offset ver_sys
dw offset ask_sys
dw offset envfree_sys
dw offset envsize_sys
dw offset mastervar_sys
dw offset add_num
dw offset sub_num
dw offset mul_num
dw offset div_num
jump_table_end = $
parse_char db "," ;Char used to parse command
fill_char db " " ;Char used to fill zeros
equalsub_char db 0cdh
databuff_ptr dw 0 ;Ptr to file data buffer
environment_seg dw 0 ;Segment of master env
dos_version dw 0
shell_name db "COMMAND"
console_out db 1 ;Flag for con out.
use_mastenv db 0 ;Flag to use master env
parse_literal db 0 ;Flag to respect lead spaces
dest_var_val dw 0
dest_var_name dw 0 ;Buffer pointers to parsed
cmd_value dw 0 ; command line variables.
var1_value dw 0 ; These pointers must be
var2_value dw 0 ; kept in this order for the
var3_value dw 0 ; cmdline parse routine.
hlpmsg db 13,10,"Usage: STRINGS [/H][/M][/Pc][environment var =]"
db " FUNCTION [str1][, str2][, str3]",13,10,13,10
db " /? - Print this help message",13,10
db " /M - Use master environment as destination",13,10
db " /Pc - Use char c instead of ',' as the parse "
db "character",13,10,10
db " LEFT Returns left n chars "
db "String, Num of chars",13,10
db " RIGHT Returns right n chars "
db "String, Num of chars",13,10
db " MID Returns middle n chars "
db "String, Start char, Length",13,10
db " LENGTH Returns string length "
db "String",13,10
db " FIND Finds position of findstring "
db "String, findstring",13,10
db " FINDC Finds position of findstring. Case sen "
db "String, findstring",13,10,0
hlpmsga db " LOWER Returns string all lowercase "
db "String",13,10
db " UPPER Returns string all uppercase "
db "String",13,10
db " CHAR Returns ASCII number of character "
db "Character",13,10
db " VAL Returns ASCII char for a number "
db "Number",13,10,10
db " READ Returns a line from a file "
db "Filename, line number",13,10
db " WRITE Writes a string to the end of a file "
db "Filename, String",13,10
db " FILESIZE Returns the size of a file "
db "Filename",13,10
db " LINESIZE Returns the number of lines "
db "Filename",13,10,0
hlpmsgb db " FILENAME Returns the file name "
db "Filename",13,10
db " FILEEXT Returns the file extension "
db "Filename",13,10
db " TRUENAME Returns the complete filename "
db "Filename",13,10,10
db " ASK Returns a response from a user "
db "[Prompt string]",13,10
db " VER Returns the DOS version number",13,10
db " ENVFREE Returns the bytes free in the environment",13,10
db " ENVSIZE Returns the size of the environment",13,10
db " MASTERVAR Returns a variable from the Master env ",13,10,10
db " ADD Returns the sum of two numbers "
db "Number, Number",13,10
db " SUB Returns the difference of two numbers "
db "Number, Number",13,10
db " MUL Returns the product of two numbers "
db "Number, Number",13,10
db " DIV Returns the quotient of two numbers "
db "Number, Number",13,10
db 0
errmsg0 db "Need DOS 2.0 or greater",0
errmsg1 db "For help type STRINGS /?",0
errmsg2 db "Not enought memory",0
errmsg3 db "Unknown command line switch",0
errmsg6 db "Illegal filename",0
errmsg7 db "Line numbers must be greater than 0",0
errmsg8 db "Line not found",0
errmsg9 db "DOS error",0
errmsg10 db "Multiply overflow error",0
errmsg11 db "Divide by zero error",0
errmsg12 db "Addition overflow",0
errmsg13 db "Subtraction underflow",0
errmsg14 db "Number too large",0
errmsg15 db "Out of environment space",0
errmsg16 db "Can't find environment",0
errmsg17 db "Variable not found",0
pausemsg db "Press any key to continue",13,10,0
endmsg db 13,10,0
;----------------------------------------------------------------------------
; Start of code.
;----------------------------------------------------------------------------
initialize proc near
assume cs:code,ds:code,es:code
cld ;Set string operations 'up.'
mov ah,30h ;Get DOS version, run only
int 21h ; if 2.0 or greater.
xchg al,ah ;Swap major, minor numbers
mov dos_version,ax
mov si,offset errmsg0 ;Bad DOS version
cmp ah,2
jae main_1
jmp disp_error
main_1:
mov di,offset end_of_code + 512 ;Set up data buffers
mov sp,di ;Set stack
mov si,offset dest_var_val
mov cx,6 ;Set buffer pointers
xor ax,ax
main_2:
mov [si],di ;Save ptr to buffer
push cx
mov cx,VAR_SIZE ;Initialize buffer to zero
rep stosb
pop cx
inc si
inc si
loop main_2
mov databuff_ptr,di ;Save data buffer ptr
mov bx,DATABUFF_SIZE
add bx,di
mov cl,4
shr bx,cl
inc bx
mov ah,4ah ;Reduce memory allocation
int 21h
call parse_cmdline ;Parse command line
jc disp_error
mov si,dest_var_name ;Point to dest env var name
call caps_string
mov si,cmd_value ;Point to command buffer
call caps_string
mov di,offset command_table
call findstr
mov si,offset errmsg1
jc disp_error
shl bx,1 ;Compute offset of routine to
add bx,offset jump_table ; call.
call [bx] ;Call routine to compile line.
jc disp_error
mov si,dest_var_val
cmp console_out,0 ;See how to return result
je main_3
call print_strcr ;Print result string to screen
jmp short main_6
main_3:
mov di,dest_var_name
xchg di,si
cmp use_mastenv,0 ;Find environment block
jne main_4
call findenv ;Use parent's env by default.
jnc main_5
main_4:
call findmaster ;Find master env
jc disp_error
main_5:
mov environment_seg,ax
call setenv ;Set environemnt variable.
jc main_7
main_6:
xor al,al ;Return code = 0
exit:
mov ah,4Ch ;Terminate
int 21h
;
;Display error message.
;
main_7:
mov si,offset errmsg15 ;Out of environment space
disp_error:
push cs
pop ds
assume ds:code
mov ah,9 ;Print copyright message
mov dx,offset program
int 21h
push si
call print_strcr ;print string
pop si
cmp si,offset hlpmsg
jne main_9
mov ax,40h
mov es,ax
mov al,es:[84h]
cmp al,42
ja main_8
call pause_scr
mov si,offset hlpmsga
call print_strcr
call pause_scr
mov si,offset hlpmsgb
call print_strcr
jmp short main_9
main_8:
mov si,offset hlpmsga
call print_strcr
mov si,offset hlpmsgb
call print_strcr
main_9:
mov al,01 ;Terminate with RC = 1
jmp short exit
;=============================================================================
; String Functions
;=============================================================================
;-----------------------------------------------------------------------------
; RIGHT STR returns the right n characters of the source string
;-----------------------------------------------------------------------------
right_str proc near
assume cs:code,ds:code,es:code
mov si,var2_value ;Convert 2nd parameter to hex
call asc2hex
call truncnum ;Truncate number to string len
push ax
mov di,var1_value ;Scan to end of string
call find_end
pop ax
right_str_2:
sub di,ax
dec di
cmp di,var1_value
ja right_str_3
mov di,var1_value
right_str_3:
mov si,dest_var_val
xchg di,si
call copy_string ;Copy string to dest buffer
clc
ret
right_str endp
;-----------------------------------------------------------------------------
; LEFT STR Returns the left n characters of the source string
;-----------------------------------------------------------------------------
left_str proc near
assume cs:code,ds:code,es:code
mov si,var2_value ;Convert 2nd parameter to hex
call asc2hex
call truncnum ;Truncate number to string len
mov si,var1_value
mov bx,ax
mov byte ptr [si+bx],0
mov di,dest_var_val
call copy_string ;Copy string to dest buffer
clc
ret
left_str endp
;-----------------------------------------------------------------------------
; MID STR Returns a string of n characters starting m characters from the
; left of the source string
;-----------------------------------------------------------------------------
mid_str proc near
assume cs:code,ds:code,es:code
mov si,var2_value ;Convert 2nd parameter to hex
call asc2hex
dec ax
call truncnum ;Truncate number to string len
mov cx,ax ;Copy second parameter
mov si,var3_value ;Convert 3rd parameter to hex
cmp byte ptr [si],0 ;See if no parameter
je mid_str_0
call asc2hex ;If no number, return max
jnc mid_str_1 ; value to insure remainder
mid_str_0:
mov ax,VAR_SIZE ; of string returned.
mid_str_1:
call truncnum ;Truncate number to string len
push ax ;Save length of substring
xor ax,ax
cmp al,1 ;Clear zero flag
mov di,var1_value ;Scan to new start of string
jcxz mid_str_11
repne scasb
mid_str_11:
pop cx ;Pop length of substring
mov si,di ;Copy ptr to start of substr
je mid_str_2 ;If end of str found, end
repne scasb ;Scan until end of substring
mov byte ptr [di],0
mid_str_2:
mov di,dest_var_val
call copy_string ;Copy string to dest buffer
clc
ret
mid_str endp
;-----------------------------------------------------------------------------
; LENGTH STR Computes the length of the source string
;-----------------------------------------------------------------------------
length_str proc near
assume cs:code,ds:code,es:code
mov di,var1_value ;Find_end also returns the
call find_end ; length of the string in
mov ax,cx ; CX.
xor dx,dx
mov di,dest_var_val ;Convert value to ASCII
call hex2asc
clc
ret
length_str endp
;-----------------------------------------------------------------------------
; UPPER STR Convert the source string to upper case
;-----------------------------------------------------------------------------
upper_str proc near
assume cs:code,ds:code,es:code
mov di,dest_var_val
mov si,var1_value
push di
call copy_string ;Copy string to dest buffer
pop si
call caps_string ;Convert to upper case.
clc
ret
upper_str endp
;-----------------------------------------------------------------------------
; LOWER STR Convert the source string to lower case
;-----------------------------------------------------------------------------
lower_str proc near
assume cs:code,ds:code,es:code
mov di,dest_var_val
mov si,var1_value
push di
call copy_string ;Copy string to dest buffer
pop si
call lc_string ;Convert to lower case.
clc
ret
lower_str endp
;-----------------------------------------------------------------------------
; CHAR STR Convert the source number to a ASCII character
;-----------------------------------------------------------------------------
char_str proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Convert ASCII number to hex
call asc2hex
mov di,dest_var_val
xor ah,ah ;Write number directly to
stosw ; dest string. Include
clc ; zero for termination.
ret
char_str endp
;-----------------------------------------------------------------------------
; VAL STR Convert the source character to its HEX equivalent
;-----------------------------------------------------------------------------
val_str proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Get ASCII character, then
lodsb ; write its hex equivalent
xor ah,ah ; to the output var.
xor dx,dx
mov di,dest_var_val
call hex2asc
clc
ret
val_str endp
;-----------------------------------------------------------------------------
; FILENAME STR Return only the filename from a filename string
;-----------------------------------------------------------------------------
filename_str proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,var2_value ;Use 2nd buff as temp buff
call parse_filename
mov si,di
mov bx,di
filename_1:
lodsb
cmp al,'\' ;Mark start of filename or
jne filename_2 ; directory.
mov bx,si
filename_2:
or al,al
je filename_3
cmp al,'.'
jne filename_1
dec si
filename_3:
mov cx,si
sub cx,bx ;Compute length
mov di,dest_var_val
mov si,bx
rep movsb
clc
ret
filename_str endp
;-----------------------------------------------------------------------------
; FILEEXT STR Return only the filename extension from a filename string
;-----------------------------------------------------------------------------
fileext_str proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,var2_value ;Use 2nd buff as temp buff
call parse_filename
mov si,di
xor bx,bx
fileext_1:
lodsb
cmp al,'.' ;Mark start of filename or
jne fileext_2 ; directory.
mov bx,si
fileext_2:
or al,al
jne fileext_1
or bx,bx
je fileext_3
mov cx,si
sub cx,bx ;Compute length
mov di,dest_var_val
mov si,bx
rep movsb
fileext_3:
clc
ret
fileext_str endp
;-----------------------------------------------------------------------------
; FIND STR finds a string within another string.
; Exit: AL - Return code if string not found
; CF - Set if string not found
;-----------------------------------------------------------------------------
find_str proc near
mov si,var1_value ;To ignore case, capitalize
call caps_string ; both strings, then call
mov si,var2_value ; the findc function.
call caps_string
call findc_str
ret
find_str endp
;-----------------------------------------------------------------------------
; FINDC STR finds a string within another string, respects case.
; Exit: AL - Return code if string not found
; CF - Set if string not found
;-----------------------------------------------------------------------------
findc_str proc near
mov di,var1_value ;Get ptr to 1st string
push di
call find_end ;Compute length
pop si
push cx ;Save length
mov di,var2_value
mov dx,di
call find_end
mov bx,cx ;Save length of search string
pop cx ;Restore length of trg string
sub cx,bx ;Sub length of search string.
jb find_str_not_found
inc cx
find_str_1:
push cx
mov cx,bx ;Restore search str length
mov di,dx ;Restore ptr to search str
push si
repe cmpsb ;Compare command
pop si
pop cx
je find_str_found
inc si ;Inc target string ptr
loop find_str_1
find_str_not_found:
xor ax,ax ;Set bad return code
jmp short find_str_2
find_str_found:
mov ax,si ;Copy offset
sub ax,var1_value ;Sub starting offset
inc ax
find_str_2:
xor dx,dx
mov di,dest_var_val ;Convert value to ASCII
call hex2asc
clc
find_str_exit:
ret
findc_str endp
;=============================================================================
; File Functions
;=============================================================================
;-----------------------------------------------------------------------------
; READ REC returns record n from a file.
;-----------------------------------------------------------------------------
readrec_file proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,dest_var_val ;Use dest buff as temp buff
call parse_filename
mov dx,di ;Copy filename pointer
call open_file
jc readrec_error
mov si,var2_value ;Convert 2nd param to record
call asc2hex ; number.
call findrec_file ;Find record.
mov ax,si ;Copy end of file flag.
mov si,offset errmsg8 ;Record not found.
jc readrec_error1 ;Error if record not found.
mov si,dest_var_val
xchg di,si
jcxz readrec_2
readrec_1:
lodsb ;Copy record to destination
cmp al,13 ; buffer.
je readrec_3
stosb
loop readrec_1
readrec_2:
or ah,ah ;Check end of file flag
jne readrec_3
mov dx,databuff_ptr ;If at end of data buffer.
mov cx,VAR_SIZE ; read enough to complete
call read_file ; record.
jc readrec_error
mov cx,ax ;Copy number of bytes read.
mov di,dx
jmp short readrec_1
readrec_3:
xor al,al ;Append terminating zero
stosb
call close_file ;Close file
jc readrec_error
readrec_exit:
ret
readrec_error:
mov si,offset errmsg9 ;Generic DOS error msg
stc
jmp short readrec_exit
readrec_error1:
call close_file
stc
jmp short readrec_exit
readrec_file endp
;-----------------------------------------------------------------------------
; WRITE REC appends a string to the end of a file.
;-----------------------------------------------------------------------------
writerec_file proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,dest_var_val ;Use dest buff as temp buff
call parse_filename
mov dx,di ;Copy filename pointer
call open_file ;Open file. If file does not
jnc writerec_0 ; exist, create the file.
call create_file
jc writerec_error
mov si,1
jmp short writerec_1
writerec_0:
xor ax,ax ;Move file ptr to end of file
cwd
mov cx,2 ;Move pointer from end.
call move_fileptr ;Move file pointer
jc writerec_error
mov si,1
or dx,dx
jne writerec_01
or ax,ax
je writerec_1
writerec_01:
mov ax,-1 ;Move file ptr to last byte
cwd
mov cx,2 ;Move pointer from end.
call move_fileptr ;Move file pointer
jc writerec_error
dec si ;Clear EOF marker flag
mov dx,dest_var_val ;Read last char to check for
mov cx,1 ; EOF marker
call read_file
jc writerec_error
mov di,dx
cmp byte ptr [di],1Ah
jne writerec_1
mov ax,-1 ;See if last byte 1A EOF mark
cwd
mov cx,2 ;Move pointer from end.
call move_fileptr ;Move file pointer
jc writerec_error
inc si ;Set EOF marker flag
writerec_1:
mov di,var2_value ;Get length of string
mov dx,di
call find_end
dec di ;Backup before zero
mov ax,0a0dh
stosw
inc cx
inc cx
or si,si
je writerec_2
mov al,1ah ;Append EOF marker
stosb
inc cx
writerec_2:
call write_file
jc writerec_error
call close_file ;Close file
jc writerec_error
writerec_exit:
mov di,dest_var_val ;Clear dest value.
mov byte ptr [di],0
ret
writerec_error:
mov si,offset errmsg9 ;Generic DOS error msg
stc
jmp short writerec_exit
writerec_error1:
call close_file
stc
jmp short writerec_exit
writerec_file endp
;-----------------------------------------------------------------------------
; NUMREC FILE returns the number of records in a file.
;-----------------------------------------------------------------------------
numrec_file proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,dest_var_val ;Use dest buff as temp buff
call parse_filename
mov dx,di ;Copy filename pointer
call open_file
jc numrec_error
xor ax,ax ;Attempt to find large rec num
mov dx,ax
call findrec_file ;Find record.
jnc numrec_error1 ;Error if record found.
not ax ;Compliment line count. No
not dx ; need to add 1 since count
; already 1 too many.
mov di,dest_var_val ;Convert rec number to ASCII
call hex2asc
call close_file ;Close file
jc numrec_error
numrec_exit:
ret
numrec_error:
mov si,offset errmsg9 ;Generic DOS error msg
stc
jmp short numrec_exit
numrec_error1:
call close_file
jc numrec_error
stc
jmp short numrec_exit
numrec_file endp
;-----------------------------------------------------------------------------
; FIND REC returns an offset to the Nth record of a file.
; Entry: DX,AX - Record to find
; BX - Source File handle
; Exit: DX,AX - Records remaing if end of file
; CF - Set if record not found.
; DI - Points to record.
; CX - Number of bytes to end of data buffer
; SI - Points to error message if CF set.
;-----------------------------------------------------------------------------
findrec_numl equ word ptr [bp-2]
findrec_numh equ word ptr [bp-4]
findrec_eof equ byte ptr [bp-5]
findrec_file proc near
assume cs:code,ds:code,es:code
push bp
mov bp,sp
sub sp,6
mov si,offset errmsg8 ;Record not found
mov findrec_eof,0 ;Clear end of file flag.
mov findrec_numl,ax ;Save record number.
mov findrec_numh,dx
findrec_1:
mov cx,databuff_ptr
xchg cx,dx
mov cx,DATABUFF_SIZE ;Get size of data buffer
call read_file ;Read data from file.
jc findrec_error
cmp ax,cx ;See if buffer filled. If
je findrec_2 ; not, end of file.
mov findrec_eof,1 ;Set end of file flag.
findrec_2:
mov cx,ax ;Copy num bytes read.
mov di,dx ;Copy buffer ptr
mov dx,ax ;Save size of buffer
mov al,13 ;Scan for CR
findrec_3:
sub findrec_numl,1 ;Decriment record count
sbb findrec_numh,0
jne findrec_4 ;See if record count = 0
cmp findrec_numl,0
je findrec_5
findrec_4:
repne scasb
je findrec_3
cmp findrec_eof,1 ;If end of buffer, see if
jne findrec_1 ; end of file. Yes = exit
stc
jmp short findrec_exit
findrec_5:
cmp byte ptr [di],0ah ;discard Line feed
jne findrec_6
inc di
dec cx
findrec_6:
clc
findrec_exit:
mov ah,findrec_eof
mov al,0
mov si,ax ;Save end of file flag
mov ax,findrec_numl ;Get record number.
mov dx,findrec_numh
mov sp,bp
pop bp
ret
findrec_error:
mov si,offset errmsg9 ;Generic DOS error msg
findrec_error1:
stc
jmp short findrec_exit
findrec_file endp
;-----------------------------------------------------------------------------
; FILE SIZE returns the size of a file
;-----------------------------------------------------------------------------
filesize_file proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,dest_var_val ;Use dest buff as temp buff
call parse_filename
mov dx,di ;Copy filename pointer
call open_file
mov di,dest_var_val ;Point DI to result buffer.
jc filesize_exit
xor ax,ax ;Zero offset.
xor dx,dx
mov cl,2 ;Move pointer from end.
call move_fileptr ;Move file pointer
jc filesize_exit
call hex2asc ;Convert size to ASCII
filesize_exit:
ret
filesize_file endp
;-----------------------------------------------------------------------------
; TRUENAME FILE returns the fully qualified name of a file.
;-----------------------------------------------------------------------------
truename_file proc near
assume cs:code,ds:code,es:code
mov si,var1_value ;Fully qualify filename
mov di,dest_var_val ;Use dest buff as temp buff
call parse_filename
jnc truename_1
mov si,offset errmsg6 ;Illegal filename msg
truename_1:
ret
truename_file endp
;=============================================================================
; System Functions
;=============================================================================
;-----------------------------------------------------------------------------
; VER SYS returns the DOS version number
;-----------------------------------------------------------------------------
ver_sys proc near
mov ax,dos_version
push ax
mov al,100
xchg al,ah ;Copy major ver number
mul ah
pop bx
xor bh,bh
add ax,bx
xor dx,dx
mov di,dest_var_val
call hex2asc
clc
ret
ver_sys endp
;-----------------------------------------------------------------------------
; ASK SYS prints a string then returns the user response.
;-----------------------------------------------------------------------------
ask_sys proc near
mov si,var1_value
cmp byte ptr [si],0
je ask_1
call print_strcr ;Print result string
ask_1:
mov bx,80h
mov byte ptr [bx],127
mov dx,bx
mov ah,0ah
int 21h
mov si,offset endmsg
call print_str ;Insert a CR-LF
xor cx,cx ;Append zero to string.
inc bx
mov cl,[bx]
inc bx
mov si,bx
add bx,cx
mov byte ptr [bx],0
inc cx
mov di,dest_var_val ;Move string to result buff
rep movsb
clc
ret
ask_sys endp
;-----------------------------------------------------------------------------
; RC SYS returns the return code from the prev process
;-----------------------------------------------------------------------------
rc_sys proc near
mov ah,4dh ;Get return code
int 21h
xor ah,ah
xor dx,dx
mov di,dest_var_val
call hex2asc
clc
ret
rc_sys endp
;-----------------------------------------------------------------------------
; ENVFREE SYS returns the number of bytes free in the environment.
;-----------------------------------------------------------------------------
envfree_sys proc near
push es
cmp use_mastenv,0 ;Find environment block
jne envfree_0
call findenv ;Use parent's env by default.
jnc envfree_01
envfree_0:
call findmaster ;Find master env
jc envfree_exit
envfree_01:
push ax
dec ax
mov es,ax
mov dx,es:[3] ;Get size of env segment
mov cl,4 ;Convert paragraphs to bytes
shl dx,cl
pop es
mov cx,dx
xor ax,ax
xor di,di
envfree_1:
repne scasb ;Loop through the environment
cmp byte ptr es:[di],al ; until the end of the
loopne envfree_1 ; env strings is found.
jcxz envfree_2
mov ax,dx
sub ax,di
dec ax ;Sub byte for extra zero
envfree_2:
xor dx,dx
pop es
mov di,dest_var_val
call hex2asc
clc
envfree_exit:
ret
envfree_sys endp
;-----------------------------------------------------------------------------
; ENVSIZE SYS returns the size of the environment.
;-----------------------------------------------------------------------------
envsize_sys proc near
push es
cmp use_mastenv,0 ;Find environment block
jne envsize_1
call findenv ;Use parent's env by default.
jnc envsize_2
envsize_1:
call findmaster ;Find master env
jc envfree_exit
envsize_2:
push ax
dec ax
mov es,ax
mov ax,es:[3] ;Get size of env segment
mov cl,4 ;Convert paragraphs to bytes
shl ax,cl
pop es
xor dx,dx
pop es
mov di,dest_var_val
call hex2asc
clc
ret
envsize_sys endp
;-----------------------------------------------------------------------------
; MASTERVAR SYS returns the value from a variable in the master environment.
;-----------------------------------------------------------------------------
mastervar_sys proc near
push ds
push es
mov di,var1_value
push di
call find_end
mov word ptr es:[di-1],003dh ;Append = sign
pop si
call caps_string
push cx ;Save length of var name
call findmaster
pop cx
jc mastervar_exit
mov es,ax
xor di,di ;Use find string routine to
call findstr ; find the variable name.
jnc mastervar_1
mov si,offset errmsg17
stc
jmp short mastervar_exit
mastervar_1:
mov si,dest_var_val
push es
push ds ;Exchange DS:SI and ES:DI
pop es ; pointers.
pop ds
xchg si,di
mastervar_2:
lodsb ;Find end of var name.
cmp al,'='
jne mastervar_2
call copy_string
clc
mastervar_exit:
pop ds
pop es
ret
mastervar_sys endp
;=============================================================================
; Number Functions
;=============================================================================
;-----------------------------------------------------------------------------
; ADD NUM returns the sum of two numbers
;-----------------------------------------------------------------------------
add_num proc near
assume cs:code,ds:code,es:code
call conv2num ;Convert first two parms to
jc add_num_exit ; 32 bit numbers. Carry
add ax,bx ; set, overflow.
adc dx,cx
mov si,offset errmsg12 ;Add overflow
jc add_num_exit ;If overflow, error
mov di,dest_var_val
call hex2asc ;Convert result to ASCII
add_num_exit:
ret
add_num endp
;-----------------------------------------------------------------------------
; SUB NUM returns the difference of two numbers
;-----------------------------------------------------------------------------
sub_num proc near
assume cs:code,ds:code,es:code
call conv2num ;Convert first two parms to
jc sub_num_exit ; 32 bit numbers. Carry
sub ax,bx ; set, overflow.
sbb dx,cx
mov si,offset errmsg13 ;Sub underflow
jc sub_num_exit
mov di,dest_var_val
call hex2asc ;Convert result to ASCII
sub_num_exit:
ret
sub_num endp
;-----------------------------------------------------------------------------
; MUL NUM returns the product of two numbers
;-----------------------------------------------------------------------------
mul_num proc near
assume cs:code,ds:code,es:code
push bp
call conv2num ;Convert first two parms to
jc mul_num_exit ; 32 bit numbers. Carry
mov di,dx ; set, overflow.
mov si,ax
mul cx ;32 bit multiply.
jc mul_num_error ;Param 1 in DI,SI
mov bp,ax ;Param 2 in CX,BX
mov ax,di
mul cx ; DI SI
or ax,dx ; CX BX
jnz mul_num_error ; ---------------------
mov ax,di ; (BX * SI)
mul bx ; (BX * DI)
jc mul_num_error ; (CX * SI)
add bp,ax ; + (CX * DI)
mov ax,si ; ---------------------
mul bx ; DX AX
add dx,bp
jc mul_num_error
mov di,dest_var_val
call hex2asc ;Convert result to ASCII
mul_num_exit:
pop bp
ret
mul_num_error:
stc
mov si,offset errmsg10 ;Multiply overflow
stc
jmp short mul_num_exit
mul_num endp
;-----------------------------------------------------------------------------
; DIV NUM returns the quotient of two numbers
;-----------------------------------------------------------------------------
div_num proc near
assume cs:code,ds:code,es:code
call conv2num ;Convert first two parms to
jc div_num_exit ; 32 bit numbers.
push cx
or cx,bx ;Prevent divide by zero
pop cx
jz div_num_error
div_num_1:
or cx,cx ;Divide both numbers by 2
je div_num_2 ; until high word of
shr dx,1 ; divisor (CX) is zero.
rcr ax,1
shr cx,1
rcr bx,1
jmp short div_num_1
div_num_2:
push ax ;Save low word
mov ax,dx
xor dx,dx
div bx ;Divide high word
mov cx,ax ;Save high quotent
pop ax
div bx ;Divide low word
mov dx,cx
mov di,dest_var_val
call hex2asc ;Convert result to ASCII
div_num_exit:
ret
div_num_error:
mov si,offset errmsg11
stc
jmp short div_num_exit
div_num endp
;=============================================================================
; Support Procedures
;=============================================================================
;-----------------------------------------------------------------------------
; CONV2NUM converts the first two parameters to hex numbers.
; Exit: DX AX - Number from 1st parameter
; CX BX - Number from 1st parameter
; CF - Set if either number too large
; SI - Set to error message if CF set
;-----------------------------------------------------------------------------
conv2num proc near
mov si,var2_value ;Convert 2nd parameter to hex
call asc2hex
jc conv2num_error
mov bx,ax ;Copy second parameter
mov cx,dx
mov si,var1_value ;Convert 1st parameter to hex
call asc2hex
jc conv2num_error
conv2num_exit:
ret
conv2num_error:
mov si,offset errmsg14 ;Number too large
jmp short conv2num_exit
conv2num endp
;-----------------------------------------------------------------------------
; PARSE CMDLINE Parse the command line into seperate buffers for each word.
; Entry: SI - Pointer to string to parse.
; Exit: CF - Set if error.
; SI - Points to error message if CF set.
;-----------------------------------------------------------------------------
parse_cmdline proc near
mov si,offset command_tail
cmp byte ptr [si],0 ;See if cmdline = 0
jne parse_cmdline_1 ;If zero, report error
parse_error:
mov si,offset errmsg1 ;Syntax error message
stc
jmp parse_cmdline_exit1
parse_cmdline_1:
inc si
xor cx,cx
xor bx,bx
call scan4char ;Find 1st char
jc parse_error
cmp al,'/' ;See if cmdline switch
jne parse_cmdline_2
inc si ;Skip past '/'.
lodsb ;Get cmdline switch
cmp al,'?'
je parse_cmdline13
or al,20h
cmp al,'m'
jne parse_cmdline_11
mov use_mastenv,1 ;Set use master env flag
jmp short parse_cmdline_1
parse_cmdline_11:
cmp al,'p'
jne parse_cmdline_12
lodsb
mov parse_char,al ;Set new parse character
jmp short parse_cmdline_1
parse_cmdline_12:
cmp al,'h'
jne parse_error
parse_cmdline13:
mov si,offset hlpmsg
stc
jmp short parse_cmdline_exit1
parse_cmdline_2:
mov di,cmd_value
mov bx,203dh ;copy until = or space
call copy_till
jc parse_cmdline_exit
cmp al,'='
je parse_cmdline_4
parse_cmdline_3:
xor bl,bl
call scan4char ;Find next char
jc parse_cmdline_exit
cmp byte ptr [si],'='
jne parse_cmdline_5
inc si ;Move src ptr past =
parse_cmdline_4:
mov console_out,0 ;Clear console out flag
xor bl,bl ;Find next char
call scan4char
jc parse_error
push si ;If = found, 1st parameter
mov si,cmd_value ; was dest var name. Copy
mov di,dest_var_name ; name, then get new cmd
call copy_string ; string.
pop si
mov bx,2020h ;Copy until next space
mov di,cmd_value
call copy_till
mov al,0 ;Terminate new cmd with 0
stosb
jc parse_cmdline_exit
parse_cmdline_5:
mov bp,offset var1_value
mov cx,3 ;Max 3 parameters
parse_cmdline_6:
xor bl,bl ;Find start of parameter
call scan4char
jc parse_cmdline_exit
mov bl,parse_char ;If consecutive parse chars
mov bh,bl ; lead a parameter, skip the
cmp [si],bx ; characters. This is used
jne parse_cmdline_7 ; to allow leading spaces in
inc si ; parameters.
inc si
parse_cmdline_7:
mov di,[bp] ;Get ptr to buffer
xor bh,bh
call copy_till ;Copy until parse char
jc parse_cmdline_exit
add bp,2
loop parse_cmdline_6
parse_cmdline_exit:
clc
parse_cmdline_exit1:
ret
parse_cmdline endp
;-----------------------------------------------------------------------------
; COPY TILL Copys a string until a specified character is found
; Entry: SI - Pointer to source string
; DI - Pointer to destination buffer
; BL - 1st end character
; BH - 2nd end character
;-----------------------------------------------------------------------------
copy_till proc near
copytill_1:
lodsb
cmp al,13 ;Check for carriage return.
je copytill_eol
copytill_2:
cmp al,equalsub_char ;See if = sub char
jne copytill_3
mov al,'='
copytill_3:
cmp al,bl ;See if end character found
je copytill_exit
cmp al,bh ;See if any char at or below
jbe copytill_exit ; 2nd end character.
stosb
jmp short copytill_1
copytill_exit:
clc
copytill_exit1:
ret
copytill_eol:
stc
jmp short copytill_exit1
copy_till endp
;-----------------------------------------------------------------------------
; PARSE FILENAME creates a proper pathname for a filename
; Entry: SI - Pointer to ASCIIZ filename
; DI - Pointer to buffer to hold resulting pathname
;-----------------------------------------------------------------------------
parse_filename proc near
assume cs:code,ds:code,es:code
push di
push si
cmp dos_version,300h ;See if DOS 3.x or greater.
jb parse_fname_0 ;If not, parse the old way.
mov ah,60h ;DOS Resolve Path
int 21h
jmp short parse_fname_7
parse_fname_0:
cmp byte ptr [SI+1],":" ;See if disk specified
je parse_fname_1 ;Yes, skip disk assignment
mov ah,19h ;Get default disk
int 21h
inc al
mov dl,al ;Save default disk number
add al,40h ;Make ASCII
mov ah,":"
jmp short parse_fname_2
parse_fname_1:
lodsw ;Get disk specified
and al,0DFh ;Convert to caps
mov dl,al
sub dl,40h ;Convert to hex
parse_fname_2:
stosw ;Load disk specification
;Look for directory specification.
mov bx,di ;save start of path
mov al,"\"
cmp byte ptr [si],al ;See if starting from root
je parse_fname_3 ;Yes, skip append of path
stosb ;Start at root
push si ;Save current pointer
mov si,di ;Point to dest buffer
mov ah,47h ;Get default path
int 21h
pop si
cmp byte ptr [di],0 ;See if NULL path
je parse_fname_3
call find_end ;Scan to end of path string
dec di ;move back before zero
mov al,"\" ;Append path string with
stosb ; a \. CX = length of path
parse_fname_3:
add cx,2 ;Append filename to path.
mov ax,VAR_SIZE ;Compute space remaining in
sub ax,cx ; the destination buffer.
xchg cx,ax
xor ah,ah ;Clear last char holder
parse_fname_4:
lodsb ;Get filename character. If
or al,al ; end of string, exit.
jz parse_fname_6 ;Else, write char.
stosb
cmp ax,".." ;If last two chars are ..,
jne parse_fname_5 ; scan backwards to delete
std ; last directory.
sub di,4 ;First, backup past '\..'
mov al,"\" ;Look for directory sep
push cx
mov cx,di ;Compute length of path
sub cx,bx
repne scasb ;Now, past last directory
pop cx
cld ;Scan forwards again
inc di ;Move back past \
parse_fname_5:
mov ah,al ;Save last character read.
loop parse_fname_4
parse_fname_6:
xor al,al ;Terminate string with 0
stosb
parse_fname_7:
pop si
pop di
ret
parse_filename endp
;-----------------------------------------------------------------------------
; CREATE FILE Creates a new file.
; Entry: DX - Pointer to ASCIIZ filename.
; Exit: BX - File handle
; CF - Set if error
;-----------------------------------------------------------------------------
create_file proc near
push cx
mov ah,3ch ;Create file
xor cx,cx ;Normal attributes
int 21h
mov bx,ax ;Copy file handle
pop cx
ret
create_file endp
;-----------------------------------------------------------------------------
; OPEN FILE Opens a file.
; Entry: DX - Pointer to ASCIIZ filename.
; Exit: BX - File handle
; CF - Set if error
;-----------------------------------------------------------------------------
open_file proc near
mov ax,3d02h ;Open file, read/write
int 21h
mov bx,ax ;Copy file handle
ret
open_file endp
;-----------------------------------------------------------------------------
; CLOSE FILE Closes a file.
; Entry: BX - File handle
; Exit: CF - Set if error
;-----------------------------------------------------------------------------
close_file proc near
mov ah,3eh ;Close file
int 21h
ret
close_file endp
;-----------------------------------------------------------------------------
; READ FILE Reads data from a file
; Entry: BX - File handle
; CX - Number of bytes to read
; DX - Pointer to data buffer
; Exit: CF - Set if error
; AX - bytes read.
;-----------------------------------------------------------------------------
read_file proc near
mov ah,3fh ;Read file data
int 21h
ret
read_file endp
;-----------------------------------------------------------------------------
; WRITE FILE Writes data to a file
; Entry: BX - File handle
; CX - Number of bytes to write
; DX - Pointer to data buffer
; Exit: CF - Set if error
;-----------------------------------------------------------------------------
write_file proc near
mov ah,40h ;Write file data
int 21h
ret
write_file endp
;-----------------------------------------------------------------------------
; MOVE FILEPTR Moves the file read pointer of a file.
; Entry: AX,DX - Offset of file pointer
; BX - File handle
; CL - Move type, 0 = from start, 2 = from end.
; Exit: CF - Set if error
;-----------------------------------------------------------------------------
move_fileptr proc near
xchg cx,dx ;Copy most sig word
xchg dx,ax ;Copy least sig word
mov ah,42h ;Move file pointer
int 21h
ret
move_fileptr endp
;-----------------------------------------------------------------------------
; TRUNCNUM truncates a number to the max length of a string
; Entry: AX - Number to truncate
; Exit: AX - Truncated number
;-----------------------------------------------------------------------------
truncnum proc near
cmp ax,VAR_SIZE ;VAR_SIZE = max string length
jb trunc_1
mov ax,VAR_SIZE
trunc_1:
ret
truncnum endp
;-----------------------------------------------------------------------------
; FINDSTR determines if a string is in a list.
; Entry: DS:SI - Pointer to ASCII string to find.
; ES:DI - Pointer to list of ASCIIZ strings.
; CX - Size of string
; Exit: DI - Pointer to entry in list
; CF - Clear if string found
; BX - If CF clear, index into list
;-----------------------------------------------------------------------------
findstr proc near
push cx
push dx
xor dx,dx
or dx,cx ;Save length of string
je finds_3
xor bx,bx ;Zero index counter
finds_1:
push di
push si
push cx
repe cmpsb ;Compare command
pop cx
pop si
pop di
clc
je findstr_exit
inc bx ;Inc string count
push cx
call find_endl ;Find end of string.
pop cx
jne finds_3
cmp byte ptr es:[di],0 ;See if second zero. If so
jne finds_1 ; end of list.
finds_3:
stc ;Indicate string not found
findstr_exit:
pop dx
pop cx
ret
findstr endp
;-----------------------------------------------------------------------------
; FIND END scans to the end of an ASCIIZ string.
; Entry: ES:DI - Pointer to ASCII string
; Exit: ES:DI - Pointers to character after string.
; CX - Length of string
; ZF - Clear if end not found in MAX length of characters
;-----------------------------------------------------------------------------
find_end proc near
push ax
mov cx,VAR_SIZE
xor al,al
repne scasb
pushf
mov ax,VAR_SIZE
sub ax,cx
xchg ax,cx
dec cx
popf
pop ax
ret
find_end endp
;-----------------------------------------------------------------------------
; FIND ENDL scans to the end of an ASCIIZ string. String can be up to 32K
; Entry: ES:DI - Pointer to ASCII string
; Exit: ES:DI - Pointers to character after string.
; CX - Length of string
; ZF - Clear if end not found in MAX length of characters
;-----------------------------------------------------------------------------
find_endl proc near
push ax
mov cx,8000h
xor al,al
repne scasb
pushf
mov ax,8000h
sub ax,cx
xchg ax,cx
dec cx
popf
pop ax
ret
find_endl endp
;-----------------------------------------------------------------------------
; CAPS STRING capitalizes ASCIIZ string
; Entry: SI - Pointer to ASCII string to capitalize
; Exit: CX - Length of string
;-----------------------------------------------------------------------------
caps_string proc near
assume ds:code,es:code
push bx
push dx
mov bx,"za" ;Set filter limits
mov dx,0df00h ;Set character filter
call filter_string
pop dx
pop bx
ret
caps_string endp
;-----------------------------------------------------------------------------
; LC STRING makes an ASCIIZ string lower case
; Entry: SI - Pointer to ASCII
; Exit: CX - Length of string
;-----------------------------------------------------------------------------
lc_string proc near
assume ds:code,es:code
push bx
push dx
mov bx,"ZA" ;Set filter limits
mov dx,0ff20h ;Set character filter
call filter_string
pop dx
pop bx
ret
lc_string endp
;-----------------------------------------------------------------------------
; FILTER STRING filters an ASCIIZ string
; Entry: DS:SI - Pointer to ASCII string
; BL - Lower limit of char range
; BH - Upper limit of char range
; DL - OR filter
; DH - AND filter
; Exit: CX - Length of string
;-----------------------------------------------------------------------------
filter_string proc near
assume ds:code,es:code
push si
push di
push es
mov di,si
push ds
pop es
xor cx,cx ;Clear byte counter.
filter_1:
lodsb ;Get character
or al,al ;Allow any non-space character
je filter_exit
cmp al,bl ;If between lower and upper
jb filter_2 ; char limit it.
cmp al,bh
ja filter_2
or al,dl ;Apply OR filter
and al,dh ;Apply AND filter
filter_2:
stosb ;Save character
inc cx ;Inc byte counter
jmp short filter_1
filter_exit:
pop es
pop di
pop si
ret
filter_string endp
;-----------------------------------------------------------------------------
; COPY STRING copies an ASCIIZ string
; Entry: DS:SI - Pointer to source ASCIIZ string
; ES:DI - Pointer to destination buffer
; Exit: CX - Length of string
;-----------------------------------------------------------------------------
copy_string proc near
assume ds:code,es:code
xor cx,cx
copy_string_1:
lodsb ;Move character
stosb
or al,al ;See if end of string
je copy_string_exit ;If so, exit
inc cx ;Inc count
jmp short copy_string_1
copy_string_exit:
ret
copy_string endp
;-----------------------------------------------------------------------------
; PRINT STRCR prints an ASCIIZ string then appends a CR LF to the end
; Entry: SI - pointer to ASCIIZ string.
;-----------------------------------------------------------------------------
print_strcr proc near
assume ds:nothing,es:nothing
call print_str
mov si,offset endmsg
call print_str
ret
print_strcr endp
;-----------------------------------------------------------------------------
; PRINT STR prints an ASCIIZ string to the std output device
; Entry: SI - Pointer to ASCIIZ string.
;-----------------------------------------------------------------------------
print_str proc near
lodsb ;Get character
or al,al ;See if end of string
je print_str_exit
mov ah,2 ;DOS print character
mov dl,al
int 21h ;Call DOS
jmp short print_str
print_str_exit:
ret
print_str endp
;-----------------------------------------------------------------------------
; HEX2ASC converts number in DX AX to ASCII
; Entry: DX AX - Number
; DI - Destination buffer
; CF - Clear
;-----------------------------------------------------------------------------
hex2asc proc near
assume ds:nothing,es:nothing
push ax
push bx
push cx
push dx
push si
mov si,10 ;Load number base
mov bx,ax
mov cx,dx
mov dx,-1 ;Load end of number flag
push dx
hex_loop1:
xchg ax,cx ;Get high word in AX
xor dx,dx ;Clear high word
div si ;Divide by base (10)
xchg cx,ax ;Save result of high divide
xchg ax,bx ;Get low word, leave remainder
div si ; in DX.
xchg bx,ax ;Save result of low divide
add dl,30h ;Convert to ascii
push dx ;Save digit on stack
or bx,bx
jne hex_loop1 ;See if number = 0. If not,
or cx,cx ; continue divide loop.
jne hex_loop1
mov bl,"0" ;Set leading zero flag
hex_loop2:
pop dx ;Get digit off stack
cmp dx,-1 ;See if end flag
je hex_2
or bl,dl ;Don't print leading zeros.
cmp bl,"0" ;The first non zero will
je hex_1 ; change bl to non-zero.
mov al,dl ;Write to buffer
stosb
hex_1:
jmp short hex_loop2
hex_2:
cmp bl,"0" ;If number zero, write last
jne hex_exit ; zero.
mov al,bl
stosb
hex_exit:
xor al,al ;Termainate with zero
stosb
pop si
pop dx
pop cx
pop bx
pop ax
ret
hex2asc endp
;-----------------------------------------------------------------------------
; ASC2HEX converts an ASCII number to hex
; Entry: SI - Pointer to ASCIIZ string, max 5 digits.
; Exit: DX,AX - Number
; CF - Set if overflow
;-----------------------------------------------------------------------------
asc2hex proc near
assume ds:nothing,es:nothing
push bx
push cx
push bp
xor cx,cx ;Zero result
xor di,di
xor bx,bx
mov bp,10 ;Load number base
asc_loop1:
mov bl,[si] ;Get next digit
inc si
sub bl,"0" ;Convert digit from ASCII to
jb asc_exit ; hex. If digit illegal
cmp bl,9 ; character, exit.
ja asc_exit
xchg ax,di ;Shift result in DI CX by
mul bp ; the base.
jc asc_exit1
xchg di,ax
xchg ax,cx
mul bp
xchg cx,ax
add di,dx
jc asc_exit1
add cx,bx ;Add new number to result.
adc di,0
jnc short asc_loop1
asc_exit1:
mov ax,cx ;Copy result
mov dx,di
pop bp
pop cx
pop bx
ret
asc_exit:
clc
jmp short asc_exit1
asc2hex endp
;-----------------------------------------------------------------------------
; SCAN4CHAR scans a string to find the first character.
; Entry: SI - pointer to ASCII string
; BL - 0 = find next char,
; 1 = find next space,
; 2 = find end of line,
; 3 = find next space or =.
; 4 = find character in DL.
; Exit: AL - matching character
; SI - pointer to matching character
; CF - set if carriage return or EOF found
;-----------------------------------------------------------------------------
scan4char proc near
assume ds:nothing,es:nothing
scan4loop:
lodsb
cmp al,13 ;Check for carriage return.
jne scan4_1
scan4_eol:
stc
jmp short scan4_exit1
scan4_1:
cmp bl,4
je scan4_dl
cmp bl,3
je scan4_equal
cmp bl,1 ;Check if searching for space,
je scan4_space ; character, or end of line.
ja scan4loop
cmp al," " ;Check for space or other
jbe scan4loop ; 'white' characters.
jmp short scan4_exit
scan4_dl:
cmp al,dl ;Check for parse character
je scan4_exit
jmp short scan4loop
scan4_equal:
cmp al,"=" ;Check for exit
je scan4_exit
scan4_space:
cmp al," " ;Check for characters.
ja scan4loop
scan4_exit:
dec si ;Back up before character
clc
scan4_exit1:
ret
scan4char endp
;-----------------------------------------------------------------------------
; PAUSE SCR Prints a 'press key' message then waits for one.
;-----------------------------------------------------------------------------
pause_scr proc near
mov si,offset pausemsg
call print_strcr
pause_1:
int 28h ;Call Idle interrupt
cld
mov ah,01 ;Check for key press
int 16h
jz pause_1
xor ax,ax ;Get key from buffer
int 16h
ret
pause_scr endp
;-----------------------------------------------------------------------------
; FINDENV Finds the parent's environment block.
; Exit: AX - Segment of local command processor environment.
;-----------------------------------------------------------------------------
findenv proc near
assume cs:code,ds:code,es:code,ss:code
push di
push si
push es
findenv_1:
mov ax,es:[16h] ;Get parent's PSP
mov dx,ax ;Save PSP segment
push ax
dec ax ;Point to mcb
mov es,ax
cmp byte ptr es:[0],"M" ;check for mcb signature
pop es
jne findenv_error
cmp dx,es:[16h] ;See if PSP is own parent
jne findenv_1 ;No, keep looking
mov cx,30
mov es,ax
findenv_2:
add ax,es:[3] ;Add size of memory block
inc ax
mov es,ax
cmp byte ptr es:[0],"M" ;check for mcb signature
jne findenv_error
cmp dx,es:[1] ;See if this owned by cmd proc
je findenv_3
loop findenv_2
jmp short findenv_error
findenv_3:
inc ax
clc
findenv_exit:
pop es
pop si
pop di
ret
findenv_error:
mov si,offset errmsg16 ;Environment not found
stc
jmp short findenv_exit
findenv endp
;-----------------------------------------------------------------------------
; FINDMASTER Finds the master environment block.
; Exit: AX - Segment of Master environment block
;-----------------------------------------------------------------------------
findmaster proc near
assume cs:code,ds:code,es:code,ss:code
push di
push si
push es
mov ah,52h ;Get address of first MCB
int 21h
mov ax,es:[bx-2] ;point ES to MCB
mov cx,30 ;Allow only 30 loops.
findmaster_1:
mov es,ax
cmp byte ptr es:[0],"M" ;check for mcb signature
jne findmaster_exit
inc ax ;point AX to memory block
cmp ax,es:[1] ;See if this is a PSP block
je findmaster_4
findmaster_2:
add ax,es:[3] ;Get size of memory block
loop findmaster_1
jmp short findmaster_error
findmaster_4:
cmp dos_version,0a00h ;If OS/2, use DOS 3.3 method.
jae findmaster_5
cmp dos_version,0400h ;If DOS 4.00 or greater,
jb findmaster_5 ; COMMAND.COM may not be the
push ds ; first program loaded. Look
mov si,offset shell_name ; at the name of the program
mov di,8 ; stored in the last 8 bytes
mov cx,7 ; of the memory control
repe cmpsb ; block. If the string
pop ds ; "COMMAND" isn't found, keep
jne findmaster_1 ; looking.
findmaster_5:
mov dx,ax ;Save PSP seg
mov es,ax
mov bx,es:[2ch] ;Get seg of prog environment
mov ax,bx
dec bx
mov es,bx
cmp byte ptr es:[0],"M" ;See if valid memory block
je findmaster_found
mov ax,dx ;Get back cmd.com segment
dec ax ;Point back to mcb
mov es,ax
findmaster_6:
add ax,es:[3] ;If master env segment not
inc ax ; saved at 2Ch of the PSP,
mov es,ax ; scan the memory blocks
cmp es:[1],dx ; for first segment owned
je findmaster_7 ; above the PSP.
loop findmaster_6
findmaster_error:
mov si,offset errmsg16 ;Master env not found msg
stc
jmp short findmaster_exit ;Master env not found.
findmaster_7:
inc ax ;Point AX to env segment
findmaster_found:
clc
findmaster_exit:
pop es
pop si
pop di
ret
findmaster endp
;-----------------------------------------------------------------------------
; SETENV Sets environment variables.
;
; Entry: DS:SI - pointer to env var name
; ES:DI - pointer to env var value
;-----------------------------------------------------------------------------
setenv proc near
push bp
push ds
push es
push di ;Save ptr to var value
push es
call find_end ;Get length of var value
mov dx,cx ;Copy length
mov di,si
push ds ;Add length of var name plus
pop es ; room for the equals sign.
call find_end
mov word ptr es:[di-1],003dh ;Append = sign
inc cx ;Add byte for =
add dx,cx
inc dx ;Add byte for terminating 0
mov ax,environment_seg
push ax
dec ax
mov es,ax
mov bp,es:[3] ;Get size of env segment
push cx
mov cl,4 ;Convert paragraphs to bytes
shl bp,cl
pop cx
pop es
xor di,di ;Use find string routine to
call findstr ; find the variable name.
push si
push ds
jc setenv_2 ;Var not found, skip erase
push es
pop ds
mov si,di ;Erase current var value by
call find_endl ; copying the next env var
xchg si,di ; over the current one.
setenv_1:
cmp byte ptr [si],0
je setenv_2
setenv_11:
lodsb
stosb
or al,al
jne setenv_11
jmp short setenv_1
setenv_2:
pop ax ;Get ptr to var name
pop cx
pop ds ;Get ptr to var value
pop si
cmp byte ptr ds:[si],0 ;See if NULL variable, If so,
je setenv_31 ; don't add to env block
mov bx,di ;Get offset of end of env
add bx,dx ;Add length of value
inc bx ;Add length of terminating byte
cmp bp,bx
ja setenv_3
push ax ;Save ptr to var name
push cx
mov dx,es
dec dx
mov es,dx
push es:[1] ;Save current owner segment
inc dx
mov es,dx
add bx,15 ;If no room in environemnt,
mov cl,4 ; see if env segment can be
shr bx,cl ; resized to make room for
mov ah,4ah ; new variable.
int 21h ;Reallocate memory
pop bx ;Get old owner
pop cx
pop ax
jc setenv_5
push es
dec dx
mov es,dx
mov es:[1],bx ;Restore old owner
pop es
setenv_3:
push si
push ds
mov si,cx
mov ds,ax
call copy_string ;Copy var name to env
dec di ;Back up over last zero
pop ds
pop si
mov bl,"=" ;Since env vars can't have
mov bh,bl ; the char '=', filter
mov dl,-1 ; string to change = to
mov dh,equalsub_char ; graphic char that looks
call filter_string ; similar.
call copy_string ;Copy var value to env
setenv_31:
xor al,al
stosb ;Add 2 zeros to end env.
setenv_4:
clc ;Set pass flag
setenv_5:
pop es
pop ds
pop bp
ret
setenv endp
initialize endp
even ;Set stack on word boundry
end_of_code = $
code ends
end main